Skip to content

fix: Adopt sessionToken from save/update response on ParseUser#1139

Open
chadpav wants to merge 3 commits into
parse-community:masterfrom
chadpav:pr/adopt-session-token
Open

fix: Adopt sessionToken from save/update response on ParseUser#1139
chadpav wants to merge 3 commits into
parse-community:masterfrom
chadpav:pr/adopt-session-token

Conversation

@chadpav

@chadpav chadpav commented May 17, 2026

Copy link
Copy Markdown
Contributor

Issue

No existing issue.

Approach

Split out from #1136 at maintainer request. This PR isolates the
session-token adoption concern.

Parse Server mints a fresh _Session row when password is set on
an existing _User (with revokeSessionOnPasswordReset = true, the
current default in parse-server 9.x). The new sessionToken is
embedded in the save response. Without adopting it, the global
session in ParseCoreData keeps pointing at the prior session —
which the server just destroyed — and every subsequent request
fails with invalidSessionToken until the next login.

This mirrors PFUser._mergeFromServerWithResult on iOS, which reads
PFUserSessionTokenRESTKey out of the response and installs it.

Implemented as _adoptResponseSessionTokenIfChanged(String?)
invoked from save() and update(). The helper is a no-op when
the response carries no sessionToken (e.g. a plain field update
with no password change), preserving the existing behavior for
non-auth saves.

Tasks

  • Add tests
  • Add changes to documentation (guides, repository pages, code comments)

Behavior change disclosure

When a _User save/update response carries a sessionToken field
(i.e. parse-server minted a new session), the SDK installs it as the
active session via ParseCoreData().setSessionId(...). Previously
the new token was merged into the local user object but the global
session continued pointing at the prior token.

Tests

packages/dart/test/src/objects/parse_user/parse_user_session_token_test.dart
— 3 tests covering:

  • save() installs a new sessionToken from the response into the global session
  • save() is a no-op when the response carries no sessionToken
  • update() installs a new sessionToken from the response

All 209 tests in packages/dart/test/ pass.

Summary by CodeRabbit

  • Bug Fixes

    • Global session token is now correctly updated from server responses during user save and update operations, preventing stale or missing session state.
  • Tests

    • Added tests validating session token adoption for save/update flows, covering responses that include or omit a session token.

Review Change Stack

Parse Server mints a fresh session row when password is set on an existing _User and revokeSessionOnPasswordReset is true (default since 9.x). The new sessionToken is embedded in the save response. Without adopting it, the global session in ParseCoreData keeps pointing at the prior session — which the server just destroyed — and every subsequent request fails with invalidSessionToken until the next login.

Mirrors PFUser._mergeFromServerWithResult on iOS, which reads PFUserSessionTokenRESTKey out of the response and installs it.

The helper is a no-op when the response carries no sessionToken (e.g. a plain field update with no password change), preserving the existing behavior for non-auth saves.
@parse-github-assistant

Copy link
Copy Markdown

🚀 Thanks for opening this pull request! We appreciate your effort in improving the project. Please let us know once your pull request is ready for review.

Tip

  • Keep pull requests small. Large PRs will be rejected. Break complex features into smaller, incremental PRs.
  • Use Test Driven Development. Write failing tests before implementing functionality. Ensure tests pass.
  • Group code into logical blocks. Add a short comment before each block to explain its purpose.
  • We offer conceptual guidance. Coding is up to you. PRs must be merge-ready for human review.
  • Our review focuses on concept, not quality. PRs with code issues will be rejected. Use an AI agent.
  • Human review time is precious. Avoid review ping-pong. Inspect and test your AI-generated code.

Note

Please respond to review comments from AI agents just like you would to comments from a human reviewer. Let the reviewer resolve their own comments, unless they have reviewed and accepted your commit, or agreed with your explanation for why the feedback was incorrect.

Caution

Pull requests must be written using an AI agent with human supervision. Pull requests written entirely by a human will likely be rejected, because of lower code quality, higher review effort and the higher risk of introducing bugs. Please note that AI review comments on this pull request alone do not satisfy this requirement. Our CI and AI review are safeguards, not development tools. If many issues are flagged, rethink your development approach. Invest more effort in planning and design rather than using review cycles to fix low-quality code.

@coderabbitai

coderabbitai Bot commented May 17, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3d668032-4fa6-4819-8dee-2fe1856ac053

📥 Commits

Reviewing files that changed from the base of the PR and between 9a3d64b and 5768574.

📒 Files selected for processing (1)
  • packages/dart/test/src/objects/parse_user/parse_user_session_token_test.dart

📝 Walkthrough

Walkthrough

ParseUser.save() and ParseUser.update() now capture the sessionToken before the network request and, on success, call _adoptResponseSessionTokenIfChanged() to update global session state from any new response sessionToken before running _onResponseSuccess(). Tests verify adoption and the no-token case.

Changes

Session Token Adoption

Layer / File(s) Summary
Session token adoption logic
packages/dart/lib/src/objects/parse_user.dart
save() and update() capture the prior sessionToken before making the network request. After a successful super.save()/super.update(), they invoke _adoptResponseSessionTokenIfChanged(tokenBefore) which updates ParseCoreData.sessionId when the post-response sessionToken is non-empty and differs from the pre-request token. A new private helper _adoptResponseSessionTokenIfChanged() implements this check and update.
Session token adoption tests
packages/dart/test/src/objects/parse_user/parse_user_session_token_test.dart
Adds tests that initialize Parse, use MockParseClient to control responses, and assert that save() and update() adopt a new sessionToken from responses and that missing tokens leave ParseCoreData.sessionId unchanged.

Sequence Diagram

sequenceDiagram
  participant ParseUser
  participant ParseClient
  participant ParseCoreData
  ParseUser->>ParseClient: super.save()/super.update() (HTTP PUT)
  ParseClient-->>ParseUser: JSON response (may include sessionToken)
  ParseUser->>ParseCoreData: _adoptResponseSessionTokenIfChanged(tokenBefore) -> setSessionId(newToken)
Loading

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 7
✅ Passed checks (7 passed)
Check name Status Explanation
Title check ✅ Passed The PR title begins with the required 'fix:' prefix and clearly summarizes the main change: adopting sessionToken from save/update response on ParseUser.
Description check ✅ Passed The PR description includes all required sections: Issue, Approach, Tasks (both checked), and goes beyond by adding Behavior change disclosure and detailed Tests section, matching the template structure.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Security Check ✅ Passed SessionToken validation implemented properly: checks null/empty, validates change, processes only after successful response. No injection or token leakage vulnerabilities found.
Engage In Review Feedback ✅ Passed No review feedback is evident in the PR. The single commit is purely a formatting change for Dart 3.10. The check requires engagement with feedback, but no feedback to address exists.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov

codecov Bot commented May 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 45.14%. Comparing base (785f76b) to head (5768574).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1139      +/-   ##
==========================================
+ Coverage   44.42%   45.14%   +0.72%     
==========================================
  Files          62       62              
  Lines        3730     3739       +9     
==========================================
+ Hits         1657     1688      +31     
+ Misses       2073     2051      -22     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/dart/test/src/objects/parse_user/parse_user_session_token_test.dart (1)

23-25: ⚡ Quick win

Restore ParseCoreData().sessionId between tests.

Each case mutates the singleton session state and leaves it behind, so later tests can inherit leaked auth state. Snapshot the prior value in setUp() and restore it in tearDown().

♻️ Suggested change
+    late String? previousSessionId;
+
     setUp(() {
+      previousSessionId = ParseCoreData().sessionId;
       client = MockParseClient();
     });
+
+    tearDown(() {
+      ParseCoreData().sessionId = previousSessionId;
+    });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/dart/test/src/objects/parse_user/parse_user_session_token_test.dart`
around lines 23 - 25, The tests mutate the singleton ParseCoreData().sessionId
and leak state across cases; modify the test harness so setUp() captures the
current ParseCoreData().sessionId into a local variable (e.g.,
previousSessionId) and tearDown() restores it to ParseCoreData().sessionId; keep
the existing MockParseClient() assignment in setUp() and ensure teardown always
runs to reset session state between tests.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@packages/dart/test/src/objects/parse_user/parse_user_session_token_test.dart`:
- Around line 23-25: The tests mutate the singleton ParseCoreData().sessionId
and leak state across cases; modify the test harness so setUp() captures the
current ParseCoreData().sessionId into a local variable (e.g.,
previousSessionId) and tearDown() restores it to ParseCoreData().sessionId; keep
the existing MockParseClient() assignment in setUp() and ensure teardown always
runs to reset session state between tests.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8b96c137-5691-4256-aa71-a15e104038db

📥 Commits

Reviewing files that changed from the base of the PR and between 785f76b and 032a0dc.

📒 Files selected for processing (2)
  • packages/dart/lib/src/objects/parse_user.dart
  • packages/dart/test/src/objects/parse_user/parse_user_session_token_test.dart

coderabbitai[bot]
coderabbitai Bot previously approved these changes May 17, 2026
Tests in this group mutate the singleton ParseCoreData().sessionId
and were not restoring it, leaking state across cases. Capture the
prior session in setUp() and restore it in tearDown() so each test
starts from a known baseline.

Addresses CodeRabbit nit on PR parse-community#1139.
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 17, 2026
CI runs `dart format --set-exit-if-changed` on Dart 3.10 stable;
the test file was written under a newer formatter style and tripped
that check. Apply the Dart 3.10 conventions (inline test name,
no trailing comma in test() argument list).
@chadpav chadpav self-assigned this May 19, 2026
@chadpav chadpav added the type:bug Impaired feature or lacking behavior that is likely assumed label May 19, 2026
@parse-github-assistant

Copy link
Copy Markdown

The label type:bug cannot be used here.

@parse-github-assistant parse-github-assistant Bot removed the type:bug Impaired feature or lacking behavior that is likely assumed label May 19, 2026
@chadpav

chadpav commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

@mtrezza anything I can do to help get these across? This sessionToken not getting saved is a high severity issue in the Flutter SDK.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant